#if !defined(GLASS_HPP)
#define GLASS_HPP

#include "Eigen"

#include "Material.hpp"
#include "utilities.hpp"

// 透明材料
class Dielectric :public Material {
private:
    // 折射率
    float eta;
    Eigen::Vector3f albedo;

public:
    Dielectric() {}
    Dielectric(
        float eta,
        Eigen::Vector3f albedo
    ) :eta(eta), albedo(albedo) {}

    ~Dielectric() {}
    virtual bool scatter(
        const Ray& rayIn, const ShadePayload& payload,
        Ray& rayOut, Eigen::Vector3f& attenuation
    )const override;
    
private:
    static double reflectance(double cosine, double ref_idx);
};

bool Dielectric::scatter(
    const Ray& rayIn, const ShadePayload& payload,
    Ray& rayOut, Eigen::Vector3f& attenuation
)const {
    float ioEta = payload.isFrontFace ? 1.f / eta : eta;
    Ray reflection(payload.pos, reflect(rayIn.direction(), payload.normal));
    Ray refraction(payload.pos, refract(rayIn.direction(), payload.normal, ioEta));
    float cosTheta = fmin((-rayIn.direction()).dot(payload.normal), 1.0);
    float sinTheta = sqrtf(1 - cosTheta * cosTheta);
    attenuation << 1, 1, 1;

    if (ioEta * sinTheta > 1.0 || reflectance(cosTheta, ioEta)>rand_float()) {
        rayOut = reflection;
    }
    else {
        rayOut = refraction;
    }

    return true;
}

double Dielectric::reflectance(double cosine, double ref_idx) {
    // Use Schlick's approximation for reflectance.
    auto r0 = (1 - ref_idx) / (1 + ref_idx);
    r0 = r0 * r0;
    return r0 + (1 - r0) * pow((1 - cosine), 5);
}

#endif // GLASS_HPP
